<?php

/**
 * 简易的ip防火墙
 * 可以用于禁止或通行两种方式
 * Class iptables
 */
class iptables
{
    //使用方法
    /*
    //检测IP，本机访问
    $ips = array("127.0.0.1", "115.159.24.194", "122.225.0.194");
    $oBlock_ip = new iptables($ips);

    if (!$oBlock_ip->isAllow()) {
        echo "禁止访问";
        exit();
    }
    */

    private $iplist;
    private $ip;

    /**
     * iptables constructor.
     * @param array $iparray 要对比的ip地址数组，可以带星号如 192.168.1.*
     */
    function __construct($iparray)
    {
        if (empty($iparray)) {
            return false;
        }
        $this->iplist = $iparray;
        $this->ip = '';
    }


    /**
     * 匹配ip
     * @param $str
     * @return string
     */
    private function makePregIP($str)
    {
        if (strstr($str, "-")) {
            $aIP = explode(".", $str);
            $preg_limit = "";
            foreach ($aIP as $k => $v) {
                if (!strstr($v, "-")) {
                    $preg_limit .= $this->makePregIP($v);
                    $preg_limit .= ".";
                } else {
                    $aipNum = explode("-", $v);
                    $preg = "";
                    for ($i = $aipNum[0]; $i <= $aipNum[1]; $i++) {
                        $preg .= $preg ? "|" . $i : "[" . $i;
                    }
                    $preg_limit .= strrpos($preg_limit, ".", 1) == (strlen($preg_limit) - 1) ? $preg . "]" : "." . $preg . "]";
                }
            }
        } else {
            $preg_limit = $str;
        }
        return $preg_limit;
    }

    /**
     * 获取设定的ip列表
     * @return array
     */
    private function getBlockIP()
    {
        $ip_list = array();
        if ($this->iplist) {
            $i = 1;
            foreach ($this->iplist as $k => $v) {
                $ipaddres = $this->makePregIP($v);
                $ip = str_ireplace(".", ".", $ipaddres);
                $ip = str_replace("*", "[0-9]{1,3}", $ip);
                $ipaddres = "/" . $ip . "/";
                $ip_list[] = $ipaddres;
                $i++;
            }
        }
        return $ip_list;
    }

    /**
     * 获取当前访问者IP
     * @return array|false|mixed|string
     */
    private function get_client_ip()
    {
        if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown")) {
            $ip = getenv("HTTP_CLIENT_IP");
        } else if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "unknown")) {
            $ip = getenv("HTTP_X_FORWARDED_FOR");
        } else if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknown")) {
            $ip = getenv("REMOTE_ADDR");
        } else if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], "unknown")) {
            $ip = $_SERVER['REMOTE_ADDR'];
        } else {
            $ip = "unknown";
        }
        $this->ip = $ip;
        return $ip;
    }

    /**
     * 检测ip是否在防火墙允许访问列表中
     * @param null $testip
     * @return bool
     */
    public function isAllow($testip = null)
    {
        $iptable = $this->getBlockIP();
        $IsJoined = false;
        if ($testip) {
            $Ip = $testip;
        } else {
            $Ip = $this->get_client_ip();
        }
//        echo $Ip;
        $Ip = trim($Ip);
        if ($iptable) {
            foreach ($iptable as $value) {
                if (preg_match("{$value}", $Ip)) {
                    $IsJoined = true;
                    break;
                }
            }
        }
        if (!$IsJoined) {
            return false;
        }
        return true;
    }

    /**
     * 当前访问者是否在禁止访问列表内
     * @param null $testip
     * @return bool
     */
    public function isDenied($testip = null)
    {
        return $this->isAllow($testip);
    }
}